home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / seyon / SeDial.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  15KB  |  655 lines

  1.  
  2. /*
  3.  * This file is part of the Seyon, Copyright (c) 1992-1993 by Muhammad M.
  4.  * Saggaf. All rights reserved.
  5.  *
  6.  * See the file COPYING (1-COPYING) or the manual page seyon(1) for a full
  7.  * statement of rights and permissions for this program.
  8.  */
  9.  
  10. #include <signal.h>
  11. #include <setjmp.h>
  12. #include <sys/types.h>
  13. #include <sys/wait.h>
  14. #include <math.h>
  15.  
  16. #include <X11/Intrinsic.h>
  17. #include <X11/StringDefs.h>
  18. #include <X11/Shell.h>
  19. #include <X11/Xaw/Command.h>
  20. #include <X11/Xaw/Dialog.h>
  21. #include <X11/Xaw/Viewport.h>
  22. #include "MultiList.h"
  23.  
  24. #include "seyon.h"
  25. #include "SeDecl.h"
  26. #include "SeSig.h"
  27.  
  28. extern char    *get_word();
  29. extern int      IconifyShell(),
  30.                 MdmReadLine(),
  31.                 MdmTimedWaitFor();
  32. extern int      ConvertStringToIntArray();
  33.  
  34. int             ReadParsePhoneFile();
  35. void            DoDial(),
  36.                 ExecDial(),
  37.                 DismissDirectory(),
  38.                 DialerEnd(),
  39.                 HighlightItems(),
  40.                 ClearAllItems(),
  41.                 ManualDial(),
  42.                 DoManualDial(),
  43.                 ReReadPhoneFile();
  44.  
  45. struct _ddItem {
  46.   char            number[LIT_BUF];
  47.   char            name[LIT_BUF];
  48.   char            baud[10];
  49.   int             bits;
  50.   int             parity;
  51.   int             stopBits;
  52.   char            prefix[LIT_BUF];
  53.   char            suffix[LIT_BUF];
  54.   char            script[SM_BUF];
  55. };
  56.  
  57. struct _ddItem *ddItems[MAX_ENT];
  58. Boolean         dialDirUp = False,
  59.                 manualDial = False;
  60. char           *script_file,
  61.                 phone_number[SM_BUF] = "",
  62.                 dialMsg[SM_BUF];
  63. int             dialTime,
  64.                 dialTry,
  65.                 current_item,
  66.                 ddCurItemIndex;
  67. jmp_buf         dial_env;
  68. XfwfMultiListWidget mlw;
  69.  
  70. /*---------------------------------------------------------------------------+
  71. | TopDial - the top routine for the dialing directory.
  72. +---------------------------------------------------------------------------*/
  73.  
  74. void
  75. TopDial(widget, clientData)
  76.      Widget          widget;
  77.      XtPointer       clientData;
  78. {
  79.   void            EditFile();
  80.  
  81.   Widget          form, mBox, uBox, lBox, view, list;
  82.   static Widget   popup;
  83.   static char     phoneFile[REG_BUF];
  84.   static String   disItems[MAX_ENT+1] = {NULL};
  85.  
  86. #ifdef DEBUG
  87.   XSynchronize(XtDisplay(widget), True);
  88. #endif
  89.  
  90.   if (clientData == NULL && dialDirUp)
  91.     SimpleError("Directory is Already Open");
  92.  
  93.   if (disItems[0] == NULL) {
  94.     strcpy(phoneFile, qres.phoneFile);
  95.     if (ReadParsePhoneFile(phoneFile, disItems) < 0) return;
  96.  
  97.     form = XtParent(widget);
  98.     popup = SeAddPopupWG("directory", widget, form, form, 0,
  99.                          SeWidgetHeight(form), True, True);
  100.     mBox = AddPaned("mBox", popup);
  101.     uBox = AddBox("uBox", mBox);
  102.     lBox = AddBox("lBox", mBox);
  103.     
  104.     view = XtCreateManagedWidget("view", viewportWidgetClass, uBox, NULL, 0);
  105.     list = XtVaCreateManagedWidget("list", xfwfMultiListWidgetClass,
  106.                                    view, XtNlist, disItems, NULL);
  107.     mlw = (XfwfMultiListWidget)list;
  108.     SeSetViewportDimFromMultiList(view, list, 10);
  109.     XtAddCallback(list, XtNcallback, DoDial, NULL);
  110.     
  111.     AddButton("dismiss", lBox, DismissDirectory, NULL);
  112.     AddButton("ok", lBox, DoDial, NULL);
  113.     AddButton("manual", lBox, ManualDial, NULL);
  114.     AddButton("clear", lBox, ClearAllItems, NULL);
  115.     AddButton("default", lBox, HighlightItems, qres.defaultPhoneEntries);
  116.     AddButton("edit", lBox, EditFile, (XtPointer)phoneFile);
  117.     AddButton("reread", lBox, ReReadPhoneFile, (XtPointer)disItems);
  118.  
  119.     XtRealizeWidget(popup);
  120.   }
  121.  
  122.   if (clientData == NULL) {
  123.     XtPopup(popup, XtGrabNone);
  124.     dialDirUp = True;
  125.     if (qres.dialAutoStart) {
  126.       qres.dialAutoStart = False;
  127.       HighlightItems(widget, qres.defaultPhoneEntries);
  128.       DoDial();
  129.     }
  130.   }
  131.   else {
  132.       HighlightItems(widget, clientData);
  133.       DoDial();
  134.     }
  135. }
  136.  
  137. /*
  138.  * DoDial: gets the first selected item and dials it.
  139.  */
  140.  
  141. void
  142. DoDial()
  143. {
  144.   static XfwfMultiListReturnStruct *item;
  145.  
  146.   ErrorIfBusy();
  147.  
  148.   if ((item = XfwfMultiListGetHighlighted(mlw))->num_selected == 0)
  149.     SimpleError("No Item Selected");
  150.   ddCurItemIndex = item->selected_items[(current_item = 0)];
  151.  
  152.   inhibit_child = True;
  153.   manualDial = False;
  154.   dialTry = 1;
  155.   
  156.   PreProcessPrep();
  157.   ExecDial();
  158. }
  159.  
  160. /*
  161.  * executes the dialing as a forked process and communicates progress
  162.  * to the main process
  163.  */
  164.  
  165. void
  166. DialHandler(
  167. #if NeedFunctionPrototypes
  168.           int signo,
  169.           XtPointer client_data
  170. #endif
  171. )
  172. {
  173.   void            DispatchActions(),
  174.                   RunScript();
  175.  
  176. #if defined(SUNOS_3) || defined(Mips)
  177.   union wait      status;
  178. #else
  179.   int             status;
  180. #endif
  181.   Widget          dirWidget;
  182.  
  183.   if (wait(&status) < 0)
  184.     {SePError("Dial wait failed"); return;}
  185.   XoAppIgnoreSignal(app_con, SIGCHLD);
  186.  
  187. #if defined(SUNOS_3) || defined(Mips)
  188.   switch (status.w_retcode) {
  189. #else
  190.   switch (WEXITSTATUS(status)) {
  191. #endif
  192.   case 0:
  193.     SeyonMessage("Connected to Remote Host");
  194.     UpdateStatusBox(NULL);
  195.     DispatchActions(ACTION_DISPATCH, qres.postConnectAction, genericWidget);
  196. #ifdef DEBUG
  197.     XSynchronize(XtDisplay(dialWidget), False);
  198. #endif
  199.     if ((dirWidget = XtNameToWidget(dialWidget, "directory"))) {
  200.       RemoveCurrentItem();
  201.       if (ddItems[ddCurItemIndex]->script[0] && !manualDial) {
  202.         linkflag = 1;
  203.         inhibit_child = False;
  204.         RunScript(NULL, ddItems[ddCurItemIndex]->script);
  205.         return;
  206.       }
  207.     }
  208.     break;
  209.   case 1:
  210.     DialCirculate();
  211.     return;
  212.   case 2:
  213.     Beep();
  214.     SeyonMessage("Dial Aborted: Online");
  215.     break;
  216.   case 10:
  217.     SeyonMessage("Dialing Canceled by User");
  218.     break;
  219.   }
  220.  
  221.   inhibit_child = False;
  222.   PostProcessPrep();
  223. }
  224.  
  225. /*
  226.  * KillDialHandler: signal handler for canceling the dialing process.
  227.  */
  228.  
  229. void
  230. KillDialHandler(
  231. #if NeedFunctionPrototypes
  232.           int signo
  233. #endif
  234. )
  235. {
  236.   void MdmOFlush();
  237.  
  238.   signal(SIGTERM, SIG_IGN);
  239.   MdmOFlush();
  240.   cancel_dial(0);
  241.   exit(10);
  242. }
  243.  
  244. void
  245. ExecDial()
  246. {
  247.   int        DialNumber();
  248.   static int retStatus;
  249.  
  250.   XoAppAddSignal(app_con, SIGCHLD, DialHandler, NULL);
  251.  
  252.   if ((w_child_pid = SeFork())) return;
  253.  
  254.   /* Child process */
  255.   signal(SIGTERM, KillDialHandler);
  256.   retStatus = DialNumber();
  257.   exit(retStatus);
  258. }
  259.  
  260. /*
  261.  * ReReadPhoneFile: updates the dialing directory from the phonebook file.
  262.  */
  263.  
  264. void
  265. ReReadPhoneFile(widget, disItems)
  266.      Widget          widget;
  267.      XtPointer       disItems[];
  268. {
  269.   Widget          dirWidget = XtParent(GetShell(widget));
  270.  
  271.   ErrorIfBusy();
  272.  
  273.   FreeList(disItems);
  274.   DestroyShell(widget);
  275.   dialDirUp = False;
  276.   TopDial(dirWidget, NULL);
  277. }
  278.  
  279. /*
  280.  * ManualDial: sets up the manual dialing popup.
  281.  */
  282.  
  283. void
  284. ManualDial(widget)
  285.      Widget          widget;
  286. {
  287.   Widget          popup;
  288.   
  289.   ErrorIfBusy();
  290.   popup = GetShell(PopupDialogGetValue("manual_dial", widget, DoManualDial, 
  291.                                        NULL, phone_number));
  292.   PopupCentered(popup, widget);
  293. }
  294.  
  295. /*
  296.  * action proc for manual dialing
  297.  */
  298.  
  299. void
  300. manual_dial_action_ok(widget)
  301.      Widget          widget;
  302. {
  303.   DoManualDial(widget);
  304. }
  305.  
  306. /*
  307.  * does manual dialing
  308.  */
  309.  
  310. void
  311. DoManualDial(widget)
  312.      Widget          widget;
  313. {
  314.   void            ExecManualDial();
  315.   Widget          dialog = XtParent(widget);
  316.   char            phoneNumber[SM_BUF];
  317.  
  318.   strcpy(phoneNumber, XawDialogGetValueString(dialog));
  319.   DestroyShell(dialog);
  320.   ExecManualDial(XtParent(GetShell(widget)), phoneNumber);
  321. }
  322.  
  323. void
  324. ExecManualDial(widget, phoneNumber)
  325.      Widget          widget;
  326.      String          phoneNumber;
  327. {
  328.   inhibit_child = True;
  329.   manualDial = True;
  330.  
  331.   strcpy(phone_number, phoneNumber);
  332.  
  333.   dialTry = 1;
  334.   PreProcessPrep();
  335.   ExecDial();
  336. }
  337.  
  338. /*
  339.  * DismissDirectory: dismisses the dialing directory.
  340.  */
  341.  
  342. void
  343. DismissDirectory(widget, clientData)
  344.      Widget          widget;
  345.      XtPointer       clientData;
  346. {
  347.   dialDirUp = False;
  348.   XtPopdown(GetShell(widget));
  349. }
  350.  
  351. /*
  352.  * ClearAllItems: clears all selected items.
  353.  */
  354.  
  355. void
  356. ClearAllItems()
  357. {
  358.   XfwfMultiListUnhighlightAll(mlw);
  359. }
  360.  
  361. void
  362. HighlightItems(widget, clientData)
  363.      Widget          widget;
  364.      XtPointer       clientData;
  365. {
  366.   int dialEntries[MAX_ENT], i;
  367.  
  368.   ConvertStringToIntArray((String*)clientData, dialEntries);
  369.  
  370.   ClearAllItems();
  371.   for (i = 0; dialEntries[i]; i++)
  372.     XfwfMultiListHighlightItem(mlw, dialEntries[i] - 1); 
  373. }
  374.  
  375. /*
  376.  * unhighlights (unselects) the current item
  377.  */
  378.  
  379. void
  380. RemoveCurrentItem()
  381. {
  382.   static XfwfMultiListReturnStruct *item;
  383.  
  384.   item = XfwfMultiListGetHighlighted(mlw);
  385.   XfwfMultiListUnhighlightItem(mlw, item->selected_items[current_item]);
  386. }
  387.  
  388. /*
  389.  * circulates to the next selected item and dials it
  390.  */
  391.  
  392. void
  393. DialCirculate()
  394. {
  395.   static XfwfMultiListReturnStruct *item;
  396.  
  397.   if (manualDial)
  398.     dialTry++;
  399.   else {
  400.     item = XfwfMultiListGetHighlighted(mlw);
  401.     if (++current_item == item->num_selected) {
  402.       current_item = 0;
  403.       dialTry++;
  404.     }
  405.     ddCurItemIndex = item->selected_items[current_item];
  406.   }
  407.  
  408.   if (qres.dialRepeat && dialTry > qres.dialRepeat) {
  409.     SeyonMessage("Max Tries Exhausted");
  410.     inhibit_child = False;
  411.     PostProcessPrep();
  412.     return;
  413.   }
  414.  
  415.   ExecDial();
  416. }
  417.  
  418. void
  419. GetStrField(raw, keyword, var, def)
  420.      String          raw,
  421.                      keyword,
  422.                      var,
  423.                      def;
  424. {
  425.   char           *ptr,
  426.                   buf[REG_BUF],
  427.                   wrd[REG_BUF];
  428.  
  429.   if ((ptr = (char*)strstr(raw, keyword)) != NULL) {
  430.     ptr += strlen(keyword);
  431.     if (strncmp(ptr, "CURRENT", 3)) {
  432.       strcpy(buf, ptr);
  433.       GetWord(buf, wrd);
  434.       strcpy(var, wrd);
  435.     }
  436.     else
  437.       strcpy(var, "CURRENT");
  438.   }
  439.   else
  440.     strcpy(var, def);
  441. }
  442.  
  443. void
  444. GetIField(raw, keyword, var, def)
  445.      String          raw,
  446.                      keyword;
  447.      int            *var,
  448.                      def;
  449. {
  450.   char            svar[TIN_BUF],
  451.                   sdef[TIN_BUF];
  452.  
  453.   sprintf(svar, "%d", *var);
  454.   sprintf(sdef, "%d", def);
  455.  
  456.   GetStrField(raw, keyword, svar, sdef);
  457.  
  458.   if (strcmp(svar, "CURRENT"))
  459.     *var = atoi(svar);
  460.   else
  461.     *var = 100;
  462. }
  463.  
  464. #define DIALALARM 5
  465.  
  466. /*
  467.  * DialTimerHandler: alarm handler for dial timeout.
  468.  */
  469.  
  470. void
  471. DialTimerHandler(dummy)
  472.      int             dummy;
  473. {
  474.   void            DialTimerHandler();
  475.  
  476.   ProcRequest(SET_MESSAGE, FmtString("%s... %d", dialMsg, 
  477.                                      dialTime -= DIALALARM, ""), "");
  478.  
  479.   if (dialTime > 0) {
  480.     signal(SIGALRM, DialTimerHandler);
  481.     alarm(DIALALARM);
  482.   }
  483.   else {
  484.     signal(SIGALRM, SIG_DFL);
  485.     alarm(0);
  486.     strcpy(dialMsg, "TIMEOUT");
  487.     longjmp(dial_env, 1);
  488.   }
  489. }
  490.  
  491. /*
  492.  * DialNumber: this routine actually does the dialing.
  493.  */
  494.  
  495. int
  496. DialNumber()
  497. {
  498.   void            MdmIFlush();
  499.   char            modemResponse[SM_BUF],
  500.                  *itemName,
  501.                  *bufPtr,
  502.                   dialString[REG_BUF];
  503.   int             i,
  504.                   k;
  505.  
  506.   if (setjmp(dial_env) != 0) {
  507.     signal(SIGALRM, SIG_DFL);
  508.     alarm(0);
  509.  
  510.     ProcRequest(SET_MESSAGE, FmtString("%s: Sleeping (%ds)...", dialMsg, 
  511.                                        qres.dialDelay, ""), "");
  512.     cancel_dial(0);
  513.     sleep(qres.dialDelay);
  514.  
  515.     return 1;
  516.   }
  517.  
  518.   k = ddCurItemIndex;
  519.   dialTime = qres.dialTimeOut;
  520.  
  521.   if (!manualDial) {
  522.  
  523.     itemName = ddItems[k]->name;
  524.     sprintf(dialString, "\r%s %s%s", ddItems[k]->prefix, ddItems[k]->number,
  525.         ddItems[k]->suffix);
  526.  
  527.     if (mbaud(ddItems[k]->baud) < 0)
  528.       se_warningf("invalid BPS value in dialing directory: %s",
  529.           ddItems[k]->baud, "", "");
  530.     if (MdmSetGetCSize(ddItems[k]->bits) < 0)
  531.       se_warningf("invalid BITS value in dialing directory: %d",
  532.           ddItems[k]->bits, "", "");
  533.     if (MdmSetGetParity(ddItems[k]->parity) < 0)
  534.       se_warningf("invalid PARITY value in dialing directory: %d",
  535.           ddItems[k]->parity, "", "");
  536.     if (MdmSetGetStopBits(ddItems[k]->stopBits) < 0)
  537.       se_warningf("invalid STOPB value in dialing directory: %d",
  538.           ddItems[k]->stopBits, "", "");
  539.   }
  540.   else {
  541.     itemName = phone_number;
  542.     sprintf(dialString, "\r%s %s%s", qres.dialPrefix, phone_number,
  543.         qres.dialSuffix);
  544.   }
  545.  
  546.   if (dialTry == 1)
  547.     sprintf(dialMsg, "Dialing %s", itemName);
  548.   else
  549.     sprintf(dialMsg, "Redialing:%d %s", dialTry, itemName);
  550.  
  551.   ProcRequest(SET_MESSAGE, "Setting Up...", "");
  552.  
  553.   if (qres.hangupBeforeDial && (qres.ignoreModemDCD || Online())) MdmHangup();
  554.   if (!qres.ignoreModemDCD && Online())    return 2;
  555.  
  556.   ProcRequest(SET_MESSAGE, FmtString("%s... %d", dialMsg, dialTime, ""), "");
  557.  
  558.   MdmIFlush();
  559.   MdmPutString(dialString);
  560.   MdmPurge();
  561.  
  562.   signal(SIGALRM, DialTimerHandler);
  563.   alarm(DIALALARM);
  564.  
  565.   while (1) {
  566.     MdmReadLine(modemResponse);
  567.  
  568.     if (*(bufPtr = StripSpace(qres.connectString)) &&
  569.         strncmp(modemResponse, bufPtr, strlen(bufPtr)) == 0) {
  570.       alarm(0);
  571.       signal(SIGALRM, SIG_DFL);
  572.       showf("\r\n%s", modemResponse, "", "");
  573.       return 0;
  574.     }
  575.  
  576.     for (i = 0; i < 3; i++)
  577.       if (*(bufPtr = StripSpace(qres.noConnectString[i])) && 
  578.           strncmp(modemResponse, bufPtr, strlen(bufPtr)) == 0) {
  579.         strcpy(dialMsg, modemResponse);
  580.         longjmp(dial_env, 1);
  581.       }
  582.   }    /* while(1)... */
  583. }
  584.  
  585. int
  586. ReadParsePhoneFile(fname, disItems)
  587.      String          fname;
  588.      String          disItems[];
  589. {
  590.   FILE           *fp;
  591.   String          rawItems[MAX_ENT + 1];
  592.   char           *buf,
  593.                  *sHold,
  594.                   disItemsBuf[REG_BUF];
  595.   int             i,
  596.                   n,
  597.                   iHold;
  598.  
  599.   if ((fp = open_file(fname, qres.defaultDirectory)) == NULL)
  600.     return -1;
  601.  
  602.   ReadCommentedFile(fp, rawItems);
  603.   fclose(fp);
  604.  
  605.   FreeList(ddItems);
  606.   for (i = 0; (buf = rawItems[i]); i++) {
  607.  
  608.     /* Allocate the record */
  609.     ddItems[i] = XtNew(struct _ddItem);
  610.  
  611.     /* Find the number */
  612.     GetWord(buf, ddItems[i]->number);
  613. /*    strcpy(ddItems[i]->number, GetFirstWord(buf));*/
  614.  
  615.     /* Find the name */
  616.     GetWord((buf = lptr), ddItems[i]->name);
  617. /*    strcpy(ddItems[i]->name, GetNextWord());*/
  618.  
  619.     /* Find other stuff */
  620.     GetStrField(buf, "BPS=", ddItems[i]->baud, qres.defaultBPS);
  621.     GetIField(buf, "BITS=", &(ddItems[i]->bits), qres.defaultBits);
  622.     GetIField(buf, "PARITY=", &(ddItems[i]->parity), qres.defaultParity);
  623.     GetIField(buf, "STOPB=", &(ddItems[i]->stopBits), qres.defaultStopBits);
  624.     GetStrField(buf, "PREFIX=", ddItems[i]->prefix, qres.dialPrefix);
  625.     GetStrField(buf, "SUFFIX=", ddItems[i]->suffix, qres.dialSuffix);
  626.     GetStrField(buf, "SCRIPT=", ddItems[i]->script, "\000");
  627.   }
  628.   ddItems[i] = (struct _ddItem *)NULL;
  629.  
  630.   FreeList(rawItems);
  631.   FreeList(disItems);
  632.  
  633.   for (n = 0; n < i; n++) {
  634.     sprintf(disItemsBuf, qres.dialDirFormat,
  635.         ddItems[n]->name,
  636.         ddItems[n]->number,
  637.         strncmp((sHold = ddItems[n]->baud), "CUR", 3) ? sHold : "????",
  638.         (iHold = ddItems[n]->bits) == 100 ? '?' : itoa(iHold),
  639.         (iHold = ddItems[n]->parity) ? (iHold == 1 ? 'O' :
  640.                         (iHold == 2 ? 'E' : '?')) : 'N',
  641.         (iHold = ddItems[n]->stopBits) == 100 ? '?' : itoa(iHold),
  642.         strncmp((sHold = ddItems[n]->prefix), "CUR", 3) ?
  643.         strcmp(sHold, qres.dialPrefix) ? 'P' : 'D' : '?',
  644.         strncmp((sHold = ddItems[n]->suffix), "CUR", 3) ?
  645.         strcmp(sHold, qres.dialSuffix) ? 'S' : 'D' : '?',
  646.         ddItems[n]->script);
  647.  
  648.     disItemsBuf[SM_BUF - 1] = '\0';
  649.     disItems[n] = XtNewString(disItemsBuf);
  650.   }
  651.   disItems[n] = NULL;
  652.  
  653.   return 0;
  654. }
  655.